package top.linruchang.util;


import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import top.linruchang.enums.MyConstants;
import top.linruchang.enums.RequestEnum;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 作用：
 *
 * @author LinRuChang
 * @version 1.0
 * @date 2020/09/06
 * @since 1.8
 **/
@Slf4j
public class HttpUtil {

    /**
     * <p>
     * description: Get请求 - 直接将参数拼接在url地址后面
     * </p>
     *
     * @param url
     * @param formParametersBean
     * @return org.apache.http.HttpResponse
     **/
    public static InputStream sendRequest(String url, Object formParametersBean) throws IOException, IllegalAccessException {
        return sendRequest(url, RequestEnum.RequestMethodEnum.GET, null, formParametersBean);
    }

    /**
     * <p>
     * description: Get请求 - 直接将参数拼接在url地址后面
     * </p>
     *
     * @param url
     * @param formParametersMap 参数
     * @return org.apache.http.HttpResponse
     **/
    public static InputStream sendRequest(String url, Map<String,String> formParametersMap) throws IOException, IllegalAccessException {
        return sendRequest(url, RequestEnum.RequestMethodEnum.GET, null, formParametersMap);
    }

    /**
     * <p>
     * description: 发送HTTP请求 - 自定义请求头以及请求携带的参数
     * </p>
     *
     * @param url                地址
     * @param requestMethod      请求方式
     * @param formParametersBean 请求参数
     * @return org.apache.http.HttpResponse
     **/
    public static InputStream sendRequest(String url, RequestEnum.RequestMethodEnum requestMethod, Map<String, String> requestHeaderMap, Object formParametersBean) throws IllegalAccessException, IOException {
        if (StrUtil.isEmpty(requestMethod.name())) {
            requestMethod = RequestEnum.RequestMethodEnum.GET;
        }
        if(! (formParametersBean instanceof Map)) {
            return sendRequest(url, requestMethod, requestHeaderMap, ReflectUtil.parseBean2Map(formParametersBean));
        }else {
            return sendRequest(url, requestMethod, requestHeaderMap, (Map)formParametersBean);
        }

    }


    /**
     * <p>
     * description: 发起Http请求
     * </p>
     *
     * @param url            请求地址
     * @param requestMethod  请求方法
     * @param formParameters 请求携带的url参数
     * @return java.lang.Object
     **/
    public static InputStream sendRequest(String url, RequestEnum.RequestMethodEnum requestMethod, Map<String, String> requestHeaderMap, Map<String, Object> formParameters) throws IOException {

        HttpClient httpClient = HttpClients.createDefault();
        HttpUriRequest httpRequest = null;

        if (RequestEnum.RequestMethodEnum.POST.equals(requestMethod)) {
            httpRequest = new HttpPost();
            //参数在请求体中并且是url编码
            if (RequestEnum.RequestContentTypeEnum.FORM_URLENCODED.getCode().equals(requestHeaderMap.get("Content-Type"))) {
                List<NameValuePair> nameValuePairs = convertMapToNameValuePairList(formParameters);
                ((HttpPost) httpRequest).setEntity(new UrlEncodedFormEntity(nameValuePairs, MyConstants.UTF_8));
                ((HttpPost) httpRequest).setURI(URI.create(url));
            } else {  //参数拼接在url上
                ((HttpPost) httpRequest).setURI(URI.create(formatUrl(url, formParameters)));
            }
        } else if (RequestEnum.RequestMethodEnum.GET.equals(requestMethod)) {
            String sendUrl = formatUrl(url, formParameters);
            //TODO 待删
            System.out.println("发送地址：" + sendUrl);
            httpRequest = new HttpGet(sendUrl);
        }

        //设置请求头
        //httpRequest.setHeaders(convertMapToHeaderArray(requestHeaderMap));
        httpRequest.setHeaders(null);

        return httpClient.execute(httpRequest).getEntity().getContent();
    }

    /**
     * <p>
     * description: parameters里面的参数解析到url后缀上 - 表单参数url
     * </p>
     *
     * @param url
     * @param parameters 参数
     * @return java.lang.String  解析后的地址
     **/
    public static String formatUrl(String url, Object parameters) {
        try {
            return formatUrl(url, ReflectUtil.parseBean2Map(parameters));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            log.info("参数添加到url地址后缀解析出错");
            return null;
        }
    }

    /**
     * <p>
     * description: 拼接成 【url?&key=value】 参数形式的字符串
     * </p>
     *
     * @param url            初始的url
     * @param formParameters 表单参数
     * @return java.lang.String
     **/
    public static String formatUrl(String url, Map<String, Object> formParameters) {
        StringBuilder sb = new StringBuilder(url + "?");
        if (ObjectUtil.isNotEmpty(formParameters)) {
            Set<Map.Entry<String, Object>> formParameterEntries = formParameters.entrySet();
            formParameterEntries.stream().filter(keyValuePair -> {
                if (ObjectUtil.isEmpty(keyValuePair.getValue())) {
                    return false;
                }
                return true;
            }).forEach(keyValuePair -> {
                sb.append(keyValuePair.getKey() + "=" + keyValuePair.getValue() + "&");
            });
        }
        if (sb.indexOf("&") != -1) {
            sb.replace(sb.length() - 1, sb.length(), "");
        }
        return sb.toString();
    }


    /**
     * @param paramMap
     * @return
     */
    public static List<NameValuePair> convertMapToNameValuePairList(Map<? extends Object, ? extends Object> paramMap) {
        List<NameValuePair> lists = new ArrayList<>();
        paramMap.entrySet().forEach(keyValuePair -> {
            if (ObjectUtil.isNotEmpty(keyValuePair.getValue())) {
                lists.add(new BasicNameValuePair((String) keyValuePair.getKey(), (String) keyValuePair.getValue()));
            }
        });
        return lists;
    }

    /**
     * Map转成BasicHeader数组
     *
     * @param requestHeaderMap
     * @return
     */
    public static Header[] convertMapToHeaderArray(Map<String, String> requestHeaderMap) {
        if (ObjectUtil.isNotEmpty(requestHeaderMap)) {
            List<BasicHeader> lists = new ArrayList<>();
            requestHeaderMap.entrySet().forEach(keyValuePair -> {
                if (ObjectUtil.isNotEmpty(keyValuePair.getValue())) {
                    lists.add(new BasicHeader(keyValuePair.getKey(), keyValuePair.getValue()));
                }
            });
            return lists.toArray(new BasicHeader[lists.size()]);
        } else {
            return new Header[1];
        }
    }

}
